export class LBQueue {
    maxBufferLen: number = 200
    forwardIndex: number = 0
    backIndex: number = 0

    constructor(forwardIndex = 0, backIndex = 0, maxBufferLen = 200) {
        this.forwardIndex = forwardIndex
        this.backIndex = backIndex
        this.maxBufferLen = maxBufferLen
    }

    maxBufferIndex() {
        return this.maxBufferLen - 1
    }

    isEmpety() {
        return this.forwardIndex == this.backIndex
    }

    isInvert() {
        return this.backIndex > this.forwardIndex
    }

    getSpaceNum() {
        if (this.isEmpety())
            return 0

        if (this.isInvert())
            return this.backIndex - this.forwardIndex - 1
        else {
            return (this.backIndex - 1) + (this.maxBufferIndex() - this.forwardIndex + 1)
        }
    }

    readableCount() {
        if (this.isEmpety())
            return 0

        if (this.isInvert())
            return (this.maxBufferIndex() - this.backIndex + 1) + (this.forwardIndex - 1)
        else {
            return this.forwardIndex - this.backIndex + 1
        }

        //return this.maxBufferLen - this.getSpaceNum()
    }

    write(num, cb) {
        for (let index = 0; index < num; index++) {
            cb(this.forwardIndex)

            let nextForwordIndex = (this.forwardIndex + 1) % this.maxBufferLen

            if (this.isInvert() && nextForwordIndex == this.backIndex) {
                this.forwardIndex = nextForwordIndex
                this.backIndex = (this.backIndex + 1) % this.maxBufferLen
            } else {
                this.forwardIndex = nextForwordIndex
            }
        }
    }

    async read(num, cb) {
        if (this.isEmpety())
            return await cb(-1)

        let length = this.readableCount()

        let index = this.backIndex



        while (num > 0 && length > 0 && index != this.forwardIndex) {
            await cb(index)

            index = (index + 1) % this.maxBufferLen
            length = length - 1
            num = num - 1
        }

        this.backIndex = index
    }

    backReadableIndex() {
        if (this.isEmpety())
            return -1

        return this.backIndex
    }

    forwardReadableIndex() {
        if (this.isEmpety())
            return -1

        return (this.forwardIndex - 1) % this.maxBufferLen
    }
}